#pragma once

#include "addrin.hpp"
#include <functional>
#include <unistd.h>
#include <strings.h>
using func_t = std::function<void(int sockfd,std::string message,AddrInt addr)>;

enum
{
    SOCKERR=1,
    BINDERR
};

class UdpServer
{

public:
    UdpServer(uint16_t port,func_t func)
    :_port(port)
    ,_func(func)
    {
        _sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd<0)
        {
            exit(SOCKERR);
        }
        struct sockaddr_in addr;
        bzero(&addr,sizeof(addr));
        addr.sin_family = AF_INET;
        // addr.sin_addr.s_addr = inet_addr("0.0.0.0");
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = htons(_port);

        int ret = bind(_sockfd,(struct sockaddr*)&addr,sizeof(addr));
        if(ret<0)
        {
            exit(BINDERR);
        }   
    }

    void start()
    {
        while (true)
        {
            /* code */
            char buff[1024];
            struct sockaddr_in addr;
            bzero(&addr,sizeof(addr));
            socklen_t len = sizeof(addr);
            ssize_t ret = recvfrom(_sockfd,buff,sizeof(buff)-1,0,(struct sockaddr*)&addr,&len);
            if(ret>0)
            {
                //接收到消息,调用回调函数
                buff[ret] = 0;
                _func(_sockfd,std::string(buff,ret),AddrInt(addr));
            }

        }
        
    }
    ~UdpServer()
    {
        if(_sockfd>=0)
            close(_sockfd);
    }
private:
    int _sockfd;
    uint16_t _port;
    func_t _func;
};